stop paging a human about upstream flapping - #19
Open
lroolle wants to merge 1 commit into
Open
Conversation
19 of the last 30 commits to this mirror changed nothing but content/.metadata.json. Upstream serves a fallback shell for a page now and then, so its manifest entry flips between a title and an error string, the tree comes back dirty, and the run does the full ceremony: an agent triage call, a commit, and a Bark push titled "DeepSeek docs updated" -- for zero documentation changes. A channel that cries wolf 19 times in 30 is not a channel. The same argument as the digest tripwire next door, arriving from the other side: there, red meant nothing because it did not separate quota from defect; here, a push means nothing because it does not separate a document change from upstream having a bad afternoon. So `Detect changes` now answers two questions instead of one. "Did the tree move?" still decides whether to commit -- the manifest is a real record and belongs in git. "Is there news?" decides whether to spend an agent call and ring a phone, and a metadata-only diff is not news: it commits quietly as chore: with no triage and no notification. That removes a signal, though, and the removed one was load-bearing by accident: the flapping was the only reason anyone would notice a page that stopped coming back for good. Aggregate freshness cannot see it -- 273 pages keep updating while one sits frozen, pipeline green, main fresh. So the manifest now records error_since: stamped when a page first fails, carried across consecutive failures, dropped the moment it recovers. That is what tells a flap from a death, and scripts/stale_sources.py reads it. The 7-day threshold is measured, not guessed. Replaying every manifest commit from 2026-08-02 to 09-02 for the three flappiest pages (news250120 en and zh-cn, news1226 en) gives 27 error spells of 0, 1, 3, 4 and 5 days. Longest is 5. Seven would have fired zero times across that month, so it stays quiet on upstream wobble and speaks only when a page has actually stopped returning. Verified: - detect logic against five real tree states (clean, metadata-only, content-only, both, untracked new page): false/false, true/false, true/true, true/true, true/true - write_manifest: first error stamps today, continued error carries the original date, recovery drops both fields, a later flap restarts the clock - stale_sources.py against 9d error, 5d error, healthy page, error with no error_since, and a malformed date: reports only the 9d one, exit 0
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
19 of the last 30 commits to this mirror changed nothing but
content/.metadata.json.Upstream serves a fallback shell for a page now and then, so its manifest entry flips between a title and an error string:
"content/en/news/news1226.md": { "url": "https://api-docs.deepseek.com/news/news1226", - "error": "served fallback shell for ... (canonical: https://api-docs.deepseek.com/)" + "title": "🚀 Introducing DeepSeek-V3"The tree comes back dirty, and the run does the full ceremony: an agent triage call, a commit, and a Bark push titled "DeepSeek docs updated" — for zero documentation changes.
A channel that cries wolf 19 times in 30 is not a channel. This is the same argument as the digest tripwire next door arriving from the other side: there, red meant nothing because it did not separate quota from defect; here a push means nothing because it does not separate a document change from upstream having a bad afternoon.
Two questions, not one
Detect changesnow answers both:changednewsworthychore:commit, no triage, no pushThe manifest still commits — it is a real record and belongs in git. It just stops being news.
The signal that was load-bearing by accident
Silencing the flapping removes the only reason anyone would notice a page that stops coming back for good. Aggregate freshness cannot see that: 273 pages keep updating while one sits frozen, pipeline green,
mainfresh.So the manifest now records
error_since— stamped when a page first fails, carried across consecutive failures, dropped the moment it recovers. That is what tells a flap from a death, andscripts/stale_sources.pyreads it. The workflow runs it every time, including on no-change runs, because a page going dead does not announce itself with a diff.The threshold is measured, not guessed
Replaying every manifest commit from 2026-08-02 to 09-02 for the three flappiest pages (
news250120en + zh-cn,news1226en) gives 27 error spells of 0, 1, 3, 4 and 5 days — longest 5:7 days would have fired zero times across that month. It stays quiet on upstream wobble and speaks only when a page has actually stopped returning.
I first read
news250120as dead since 2026-08-08 — the commit log says "fallback shell" over and over. Replaying the manifest showed it flapping ok→ERR 16 times instead, current spell 4 days. That is exactly the page this threshold has to not fire on.Verification
false·false,true·false,true·true,true·true,true·truewrite_manifest— first error stamps today; continued error carries the original date rather than bumping it; recovery drops both fields; a later flap restarts the clockstale_sources.pyagainst a 9-day error, a 5-day error, a healthy page, an error with noerror_since, and a malformed date → reports only the 9-day one, exit 0Note
On the first run after merge every currently-failing page gets
error_since= that day, so the clock starts fresh. Nothing is currently near 7 days (longest live spell is 4), so the check should stay silent — that is the expected result, not a broken check.